package com.superhelper.superhelper_web.service;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.superhelper.common.domain.AuserShop;
import com.superhelper.common.domain.TakeOutShopInfo;
import com.superhelper.common.service.RedisService;
import com.superhelper.common.utils.JsonHelper;
import com.superhelper.common.utils.ThreadPool;
import com.superhelper.superhelper_web.common.Consts;
import com.superhelper.superhelper_web.domain.AccessToken;
import com.superhelper.superhelper_web.domain.AuserShopAudio;
import com.superhelper.superhelper_web.mapper.AdminMapper;

import eleme.openapi.sdk.oauth.response.Token;

@Service
public class ShopService {
	protected Logger log = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private AdminMapper adminMapper;
	@Autowired
	private RedisService redisService;
	@Autowired
	private ElemeService elemeService;
	@Autowired
	private ThreadPool threadPool;
	@Autowired
	private MtService mtService;

	public List<AuserShop> selectList(Integer auserId) {
		return adminMapper.selectList(auserId);
	}

	public List<AuserShop> getInitShop() {
		List<AuserShop> shops = new ArrayList<AuserShop>();
		AuserShop shopEle = new AuserShop();
		shopEle.setShop_type(AuserShop.SHOP_ELEME);
		shopEle.setState(0);
		shops.add(shopEle);
		AuserShop shopMt = new AuserShop();
		shopMt.setShop_type(AuserShop.SHOP_MEITUAN);
		shopMt.setState(0);
		shops.add(shopMt);
		return shops;
	}

	public String getAuthUrl(Integer auserId, String type)
			throws UnsupportedEncodingException {
		if (type.equals(AuserShop.SHOP_ELEME)) {
			return elemeService.getAuthUrl(auserId);
		} else {
			String ePoiId = System.currentTimeMillis()
					+ String.valueOf(auserId);
			return mtService.getAuthUrl(auserId, ePoiId);
		}
	}

	public boolean elemeAuthCallBack(Integer auserId, String code) {
		try {
			// 根据OAuth2.0中的对应state，scope和callback_url，获取授权URL
			Token token = elemeService.getTokenByCode(code);
			log.info("[checkAuthCallBack]token:{}", JsonHelper.toJson(token));
			if (!token.isSuccess()) {
				log.error("[checkAuthCallBack]token error:{}", auserId);
				return false;
			}

			final AccessToken accessToken = new AccessToken();
			accessToken.setExpires(token.getExpires());
			accessToken.setRefreshToken(token.getRefreshToken());
			accessToken.setTokenType(token.getTokenType());
			accessToken.setToken(token.getAccessToken());
			accessToken.setTokenAt(new Date());
			String shopId = elemeService.getShopId(token);
			accessToken.setShopId(shopId);

			AuserShop shop = adminMapper.getAuserShopByShopId(shopId,
					AuserShop.SHOP_ELEME);
			if (shop == null) {// 没绑定过
				shop = new AuserShop();
				shop.setToken(JsonHelper.toJson(accessToken));
				shop.setAuserId(auserId);
				shop.setShopId(shopId);
				shop.setShop_type(AuserShop.SHOP_ELEME);
				shop.setState(1);
				int res = adminMapper.addAuserShop(shop);
				log.info("[checkAuthCallBack]res:{}", res);
			} else {

				adminMapper.updateShopToken(shopId, AuserShop.SHOP_ELEME,
						JsonHelper.toJson(accessToken));
			}
			String token_key = Consts.Cache.ELEME_TOKEN + shopId;
			redisService.set(token_key, accessToken);

			threadPool.submit(new Runnable() {
				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						TakeOutShopInfo shop = getShopInfo(
								accessToken.getShopId(), AuserShop.SHOP_ELEME);
						adminMapper.updateShopPoi(accessToken.getShopId(),
								AuserShop.SHOP_ELEME, shop.getLatitude(),
								shop.getLongitude());
					} catch (Exception e) {
						// TODO Auto-generated catch block
						log.error("", e);
					}
				}
			});

			log.info("[checkAuthCallBack]shop:{}", JsonHelper.toJson(shop));
			return true;
		} catch (Exception e) {
			log.error("[checkAuthCallBack]error:{}", e);
			return false;
		}
	}

	public TakeOutShopInfo getShopInfo(String shopId, String type)
			throws Exception {
		String key = Consts.Cache.SUPER_SHOP + type + shopId;
		TakeOutShopInfo shop = redisService.get(key, TakeOutShopInfo.class);
		if (shop == null) {
			if (AuserShop.SHOP_ELEME.equals(type)) {
				shop = elemeService.getShopInfo(shopId);
			} else {
				shop = mtService.getShopInfo(shopId);
			}
			redisService.set(key, 600, shop);
		}
		return shop;
	}

	public List<AuserShop> getAuserShopsByAuserId(Integer auserId) {
		return adminMapper.getAuserShopsByAuserId(auserId);
	}

	public List<String> getAuserShopIdsByAuserId(Integer auserId) {
		List<AuserShop> list = this.getAuserShopsByAuserId(auserId);
		List<String> ids = new ArrayList<String>();
		for (AuserShop s : list) {
			ids.add(s.getShopId());
		}
		return ids;
	}

	public int updateOrderSwitch(Integer id, int orderAuto) {
		return adminMapper.updateOrderAuto(id, orderAuto);
	}

	public int updateDeliverSwitch(Integer id, int deliverType,
			String deliverUid, String deliverShopNo) {
		return adminMapper.updateDeliverSwitch(id, deliverType, deliverUid,
				deliverShopNo);
	}

	public boolean mtAuthCallBack(Integer auserId, String shopId, String token) {
		try {
			if (StringUtils.isBlank(token)) {
				log.error("[checkAuthCallBack]token error:{}", auserId);
				return false;
			}
			final AccessToken accessToken = new AccessToken();
			Long expires = System.currentTimeMillis();
			accessToken.setExpires(expires);
			accessToken.setRefreshToken(token);
			accessToken.setTokenType("mt");
			accessToken.setToken(token);
			accessToken.setTokenAt(new Date());
			accessToken.setShopId(shopId);

			AuserShop shop = adminMapper.getAuserShopByShopId(shopId,
					AuserShop.SHOP_MEITUAN);
			if (shop == null) {// 没绑定过
				shop = new AuserShop();
				shop.setToken(JsonHelper.toJson(accessToken));
				shop.setAuserId(auserId);
				shop.setShopId(shopId);
				shop.setShop_type(AuserShop.SHOP_MEITUAN);
				shop.setState(1);
				int res = adminMapper.addAuserShop(shop);
				log.info("[checkAuthCallBack]res:{}", res);
			} else {
				int res = adminMapper.updateShopToken(shopId,
						AuserShop.SHOP_MEITUAN, JsonHelper.toJson(accessToken));
				log.info("[updateShopToken]res:{}", res);
			}
			String token_key = Consts.Cache.MT_TOKEN + shopId;
			redisService.set(token_key, accessToken);

			threadPool.submit(new Runnable() {
				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						TakeOutShopInfo shop = getShopInfo(
								accessToken.getShopId(), AuserShop.SHOP_MEITUAN);
						adminMapper.updateShopPoi(accessToken.getShopId(),
								AuserShop.SHOP_MEITUAN, shop.getLatitude(),
								shop.getLongitude());
					} catch (Exception e) {
						log.error("", e);
					}

				}
			});

			log.info("[checkAuthCallBack]shop:{}", JsonHelper.toJson(shop));
			return true;
		} catch (Exception e) {
			log.error("[checkAuthCallBack]error:{}", e);
			return false;
		}
	}

	public List<AuserShopAudio> getAuserAudioByAuserId(Integer auserId) {
		List<AuserShopAudio> baseList = adminMapper.getAuserAudioByAuserId(0);
		List<AuserShopAudio> audios = adminMapper
				.getAuserAudioByAuserId(auserId);
		if (!audios.isEmpty()) {
			for (AuserShopAudio a : audios) {
				for (AuserShopAudio b : baseList) {
					if (b.getType().equals(a.getType())) {
						b.setCount(a.getCount());
					}
				}
			}
		}
		return baseList;
	}

	@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
	public int saveAudio(List<AuserShopAudio> list) {
		for (AuserShopAudio a : list) {
			adminMapper.addAudio(a);
		}
		return list.size();
	}

	public boolean openShop(String shopId, String type, Integer state)
			throws Exception {
		boolean result = false;
		String key = Consts.Cache.SUPER_SHOP + type + shopId;
		if (AuserShop.SHOP_ELEME.equals(type)) {
			result = elemeService.openShop(shopId, state);
		} else {
			result = mtService.mtOpen(shopId, state);
		}
		redisService.delKey(key);
		return result;
	}

}
